package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.runner;

import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.feign.service.RoleFeignService;
import com.alibaba.algo.cooperation.feign.vo.req.SelectRoleUserReqVO;
import com.alibaba.algo.cooperation.feign.vo.res.RoleUserInfoResVO;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.FlowUserTaskRoleInfoVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowUserTaskRoleInfoRepository;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.DynamicBpmnService;
import org.flowable.engine.ManagementService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.common.impl.interceptor.Command;
import org.flowable.engine.common.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author: niechanggang
 * @date:2021/8/17 14:59
 * @description:
 */
@Service
public class DynamicBpmnRunner  implements ApplicationRunner {

    private Logger  logger = LoggerFactory.getLogger(this.getClass());

    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ManagementService managementService;

    @Autowired
    private FlowUserTaskRoleInfoRepository flowUserTaskRoleInfoRepository;

    @Autowired
    private RoleFeignService roleFeignService;

    @Autowired
    private DynamicBpmnService dynamicBpmnService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                managementService.executeCommand(new Command<Void>() {
                    public  Void execute(CommandContext commandContext){
                        List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery().list();
                        for(ProcessDefinition processDefinition : definitionList){
                            String defId = processDefinition.getId();
                            String deployId = processDefinition.getDeploymentId();
                            Process process = ProcessDefinitionUtil.getProcess(defId);
                            Collection<FlowElement> flowElements = process.getFlowElements();
                            for(FlowElement flowElement : flowElements){
                                if(flowElement instanceof UserTask){
                                    UserTask userTask = (UserTask)flowElement;
                                    String nodeCode = userTask.getId();
                                    FlowUserTaskRoleInfoVo  flowUserTaskRoleInfoVo = flowUserTaskRoleInfoRepository.selectByDeployIdAndNodeCode(deployId, nodeCode);
                                    if(flowUserTaskRoleInfoVo != null){
                                        String  candidateUsersStr = flowUserTaskRoleInfoVo.getCandidateUsers();
                                        String  roleIdsStr =  flowUserTaskRoleInfoVo.getRoleIds();
                                        if(StringUtils.isNotEmpty(roleIdsStr)){
                                            Set<String> candidateUsers = new HashSet<>();
                                            if(StringUtils.isNotEmpty(candidateUsersStr)){
                                                String[] candidateUserArr =  candidateUsersStr.split(",");
                                                for(String candidateUser : candidateUserArr){
                                                    candidateUsers.add(candidateUser);
                                                }
                                            }
                                            String[] roleIdArr = roleIdsStr.split(",");
                                            for(String roleId : roleIdArr){
                                                SelectRoleUserReqVO  selectRoleUserReqVO = new  SelectRoleUserReqVO();
                                                selectRoleUserReqVO.setRoleId(Long.parseLong(roleId));
                                                BaseResult<List<RoleUserInfoResVO>> result = roleFeignService.qryUserListByRoleId(selectRoleUserReqVO);
                                                List<RoleUserInfoResVO> dataList = result.getData();
                                                if(dataList != null){
                                                    for(RoleUserInfoResVO  roleUserInfoResVO : dataList){
                                                        candidateUsers.add(roleUserInfoResVO.getUserId()+"");
                                                    }
                                                }
                                            }
                                            List<String> candidateUserList = new ArrayList<>(candidateUsers);
                                            ObjectNode users = dynamicBpmnService.changeUserTaskCandidateUsers(nodeCode, new ArrayList<>(candidateUserList));
                                            dynamicBpmnService.saveProcessDefinitionInfo(defId, users);
                                            logger.info("DefId:"+defId+" CandidateUsers"+candidateUserList.size());
                                        }
                                    }
                                }
                            }
                        }
                        return null;
                    }
                });

            }
        };
        //scheduledExecutorService.scheduleAtFixedRate(runnable, 0,5, TimeUnit.MINUTES);
    }
}
